import json
import pandas as pd
from datetime import datetime
import platform
import numpy as np


def generate_validation_outputs(
    folds_results,
    metrics_dict,
    *,
    model_name,              # ✅ 必填
    model_version,           # ✅ 必填
    framework,               # ✅ 必填
    target="SalePrice",
    train_size=None,
    n_features=None,
    n_splits=5,
    random_state=42,
    training_time="00:00:00",
    notes="",
    args=None
):
    """
    自动生成交叉验证报告与验证集预测文件（支持记录模型参数与准确率）

    参数说明：
    ----------
    folds_results : list[dict]
        每折预测结果，包含 ["fold", "Id", "y_true", "y_pred"]
    metrics_dict : dict
        各指标交叉验证结果，如：
        {
            "RMSE": {"folds": [...], "mean": 0.12, "std": 0.01},
            "MAE": {"folds": [...], "mean": 0.09, "std": 0.002},
            "R2": {"folds": [...], "mean": 0.915, "std": 0.0015}
        }
    model_name, model_version, framework : str
        必选项
    args : dict (可选)
        模型训练参数，如 {"learning_rate": 0.05, "n_estimators": 500, "max_depth": 6}
    """

    # --- 1️⃣ 校验输入 ---
    df_val = pd.DataFrame(folds_results)
    required_cols = {"fold", "Id", "y_true", "y_pred"}
    if not required_cols.issubset(df_val.columns):
        raise ValueError(f"❌ folds_results 必须包含字段: {required_cols}")

    df_val["residual"] = df_val["y_true"] - df_val["y_pred"]

    # --- 2️⃣ 文件命名规则 ---
    csv_filename = f"validation_{framework.lower()}.csv"
    json_filename = f"validation_report_{framework.lower()}.json"

    # --- 3️⃣ 保存验证集预测结果 ---
    df_val.to_csv(csv_filename, index=False)
    print(f"✅ Saved validation results -> {csv_filename}")

    # --- 4️⃣ 计算额外的准确率指标（如R²或Accuracy）---
    acc_metric = None
    for key in ["Accuracy", "R2", "r2_score"]:
        if key in metrics_dict:
            acc_metric = metrics_dict[key]["mean"]
            break

    # --- 5️⃣ 构建报告结构 ---
    report = {
        "model_info": {
            "model_name": model_name,
            "version": model_version,
            "framework": framework,
            "created_at": datetime.now().isoformat()
        },
        "data_info": {
            "train_size": train_size,
            "n_features": n_features,
            "target": target,
            "cv_method": "KFold",
            "n_splits": n_splits,
            "shuffle": True,
            "random_state": random_state
        },
        "metrics": metrics_dict,
        "training_summary": {
            "training_time": training_time,
            "cross_val_accuracy": acc_metric,   # ✅ 自动补充平均准确率
            "notes": notes
        },
        "environment": {
            "python": platform.python_version(),
            "os": platform.system(),
            "machine": platform.machine()
        },
        "model_args": args or {}
    }

    # --- 6️⃣ 保存 JSON 报告 ---
    with open(json_filename, "w", encoding="utf-8") as f:
        json.dump(report, f, indent=2, ensure_ascii=False)

    print(f"✅ Saved cross-validation report -> {json_filename}")


# 🧠 示例调用
if __name__ == "__main__":
    folds_results = [
        {"fold": 1, "Id": 1001, "y_true": 200000, "y_pred": 195230},
        {"fold": 1, "Id": 1002, "y_true": 185000, "y_pred": 183900},
        {"fold": 2, "Id": 1003, "y_true": 250000, "y_pred": 251100},
    ]

    metrics_dict = {
        "RMSE": {"folds": [0.1201, 0.1187, 0.1210, 0.1198, 0.1205], "mean": 0.1200, "std": 0.0010},
        "MAE": {"folds": [0.089, 0.091, 0.090, 0.087, 0.088], "mean": 0.089, "std": 0.0016},
        "R2": {"folds": [0.915, 0.917, 0.914, 0.916, 0.913], "mean": 0.915, "std": 0.0015}
    }

    generate_validation_outputs(
        folds_results,
        metrics_dict,
        model_name="XGBoost Regressor",
        model_version="1.0.1",
        framework="xgboost",
        train_size=1460,
        n_features=80,
        training_time="00:04:32",
        notes="Model shows stable performance across folds.",
        args={
            "learning_rate": 0.05,
            "n_estimators": 500,
            "max_depth": 6,
            "subsample": 0.8,
            "colsample_bytree": 0.8,
            "reg_lambda": 1.0
        }
    )
